#include <avr/io.h>
#include <avr/interrupt.h>
#include "global.h"
#include "rf01.h"

#define F_CPU 10000000UL
#include <util/delay.h>

#define RF_PORT	PORTB
#define RF_DDR	DDRB
#define RF_PIN	PINB

#define SDI		5	// SDI,  -> RF02
#define SCK		6	// SCK,  -> RF02
#define CS		7	// nSEL, -> RF02
#define SDO		0	// SDO,  <- RF02

// nFFS: 1-10k Pullup an Vcc !!!

static unsigned char sdrssi, sgain;

void rf01_trans(unsigned short wert)
{	unsigned char i;

	cbi(RF_PORT, CS);
	for (i=0; i<16; i++)
	{	if (wert&32768)
			sbi(RF_PORT, SDI);
		else
			cbi(RF_PORT, SDI);
		sbi(RF_PORT, SCK);
		wert<<=1;
		_delay_us(0.2);
		cbi(RF_PORT, SCK);
	}
	sbi(RF_PORT, CS);
}

void rf01_init(void)
{	unsigned char i;
	RF_PORT=(1<<CS);
	RF_DDR=(1<<SDI)|(1<<SCK)|(1<<CS);

	for (i=0; i<11; i++)
		_delay_ms(10);			// wait until POR done

	rf01_trans(0xC2E0);			// AVR CLK: 10MHz
	rf01_trans(0xC42B);			// Data Filter: internal
	rf01_trans(0xCE88);			// FIFO mode
	rf01_trans(0xC6F7);			// AFC settings: autotuning: -10kHz...+7,5kHz
	rf01_trans(0xE000);			// disable wakeuptimer
	rf01_trans(0xCC00);			// disable low duty cycle
}

void rf01_setbandwidth(unsigned char bandwidth)
{
	rf01_trans(0x8970|((bandwidth&7)<<1));
}

void rf01_setreceiver(unsigned char gain, unsigned char drssi)
{
	sdrssi=drssi;
	sgain=gain;
}

void rf01_setfreq(unsigned short freq)
{	if (freq<96)				// 430,2400MHz
		freq=96;
	else if (freq>3903)			// 439,7575MHz
		freq=3903;
	rf01_trans(0xA000|freq);
}

void rf01_setbaud(unsigned short baud)
{
	if (baud<336)
		return;
	if (baud<5400)				// Baudrate= 344827,58621/(R+1)/(1+CS*7)
		rf01_trans(0xC880|((43104/baud)-1));
	else
		rf01_trans(0xC800|((344828UL/baud)-1));
}

void rf01_rxdata(unsigned char *data, unsigned char number)
{	unsigned char i,j,c;

	rf01_trans(0xC0C1|((sgain&3)<<4)|((sdrssi&7)<<1));	// RX on
	rf01_trans(0xCE89);			// set FIFO mode
	rf01_trans(0xCE8B);			// enable FIFO
	cbi(RF_PORT, SDI);
	for (i=0; i<number; i++)
	{	cbi(RF_PORT, CS);
		while (!(RF_PIN&(1<<SDO))); // wait until data in FIFO
		for (j=0; j<16; j++)	// read and discard status register
		{	sbi(RF_PORT, SCK);
			asm("nop");
			cbi(RF_PORT, SCK);
		}
		c=0;
		for (j=0; j<8; j++)
		{	c<<=1;
			if (RF_PIN&(1<<SDO))
				c|=1;
			sbi(RF_PORT, SCK);
			_delay_us(0.2);
			cbi(RF_PORT, SCK);
		}
		*data++=c;
		sbi(RF_PORT, CS);
	}
	rf01_trans(0xC0C0|((sgain&3)<<4)|((sdrssi&7)<<1));	// RX off
}

